Hands-on_Ex03

Interactive Data Visualization

Getting started

Install and launch R packages

pacman::p_load(ggiraph, plotly, 
               patchwork, DT, tidyverse) 

Import data

exam_data <- read_csv("data/Exam_data.csv")
Rows: 322 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (4): ID, CLASS, GENDER, RACE
dbl (3): ENGLISH, MATHS, SCIENCE

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Interactive Data Visualization

ggigraph methods

tooltip aesthetic

First, create an interactive ggplot object with geom_dotplot_interactive()

ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(
    aes(tooltip = ID),
    stackgroups = TRUE, 
    binwidth = 1, 
    method = "histodot") +
  scale_y_continuous(NULL, 
                     breaks = NULL)

Next, use girafe() to create an interactive svg object: student’s ID displayed when mouse pointer hover on a data point of interest

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(
    aes(tooltip = ID),
    stackgroups = TRUE, 
    binwidth = 1, 
    method = "histodot") +
  scale_y_continuous(NULL, 
                     breaks = NULL)
girafe(
  ggobj = p,
  width_svg = 6,
  height_svg = 6*0.618
)

Display multiple information on tooltip

Include a list object in the content of the tooltip.

exam_data$tooltip <- c(paste0(     
  "Name = ", exam_data$ID,         
  "\n Class = ", exam_data$CLASS)) 

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(
    aes(tooltip = exam_data$tooltip), 
    stackgroups = TRUE,
    binwidth = 1,
    method = "histodot") +
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(
  ggobj = p,
  width_svg = 8,
  height_svg = 8*0.618
)

Customize tooltip style Use opts_tooltip() of ggiraph to customize tooltip rendering by adding ccs declarations

tooltip_css <- "background-color:white; #<<
font-style:bold; color:black;" #<<

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(              
    aes(tooltip = ID),                   
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") +               
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(                                  
  ggobj = p,                             
  width_svg = 6,                         
  height_svg = 6*0.618,
  options = list(    #<<
    opts_tooltip(    #<<
      css = tooltip_css)) #<<
)                                        

Display statistics on tooltip

tooltip <- function(y, ymax, accuracy = .01) {
  mean <- scales::number(y, accuracy = accuracy)
  sem <- scales::number(ymax - y, accuracy = accuracy)
  paste("Mean maths scores:", mean, "+/-", sem)
}

gg_point <- ggplot(data=exam_data, 
                   aes(x = RACE),
) +
  stat_summary(aes(y = MATHS, 
                   tooltip = after_stat(  
                     tooltip(y, ymax))),  
    fun.data = "mean_se", 
    geom = GeomInteractiveCol,  
    fill = "light blue"
  ) +
  stat_summary(aes(y = MATHS),
    fun.data = mean_se,
    geom = "errorbar", width = 0.2, size = 0.2
  )
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
girafe(ggobj = gg_point,
       width_svg = 8,
       height_svg = 8*0.618)

Hover effect with data_id aesthetic

Default value hover_css=“fill:orange;”

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(           
    aes(data_id = CLASS),             
    stackgroups = TRUE,               
    binwidth = 1,                        
    method = "histodot") +               
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(                                  
  ggobj = p,                             
  width_svg = 6,                         
  height_svg = 6*0.618                      
)                                        

Style hover effect

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(              
    aes(data_id = CLASS),              
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") +               
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(                                  
  ggobj = p,                             
  width_svg = 6,                         
  height_svg = 6*0.618,
  options = list(                        
    opts_hover(css = "fill: #202020;"),  
    opts_hover_inv(css = "opacity:0.2;") 
  )                                        
)                                        

Combine tooltip and hover effect

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(              
    aes(tooltip = CLASS, 
        data_id = CLASS),              
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") +               
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(                                  
  ggobj = p,                             
  width_svg = 6,                         
  height_svg = 6*0.618,
  options = list(                        
    opts_hover(css = "fill: #202020;"),  
    opts_hover_inv(css = "opacity:0.2;") 
  )                                        
)                                        

Click effect with onclick

exam_data$onclick <- sprintf("window.open(\"%s%s\")",
"https://www.moe.gov.sg/schoolfinder?journey=Primary%20school",
as.character(exam_data$ID))

p <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(              
    aes(onclick = onclick),              
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") +               
  scale_y_continuous(NULL,               
                     breaks = NULL)
girafe(                                  
  ggobj = p,                             
  width_svg = 6,                         
  height_svg = 6*0.618)                                        

Coordinated multiple views with ggiraph

p1 <- ggplot(data=exam_data, 
       aes(x = MATHS)) +
  geom_dotplot_interactive(              
    aes(data_id = ID),              
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") +  
  coord_cartesian(xlim=c(0,100)) + 
  scale_y_continuous(NULL,               
                     breaks = NULL)

p2 <- ggplot(data=exam_data, 
       aes(x = ENGLISH)) +
  geom_dotplot_interactive(              
    aes(data_id = ID),              
    stackgroups = TRUE,                  
    binwidth = 1,                        
    method = "histodot") + 
  coord_cartesian(xlim=c(0,100)) + 
  scale_y_continuous(NULL,               
                     breaks = NULL)

girafe(code = print(p1 + p2), 
       width_svg = 6,
       height_svg = 3,
       options = list(
         opts_hover(css = "fill: #202020;"),
         opts_hover_inv(css = "opacity:0.2;")
         )
       ) 

plotly methods

plot_ly() method

plot_ly(data = exam_data, 
        x = ~ENGLISH, 
        y = ~MATHS, 
        color = ~RACE)
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

ggplotly() method

p <- ggplot(data=exam_data, 
            aes(x = MATHS,
                y = ENGLISH)) +
  geom_point(size=1) +
  coord_cartesian(xlim=c(0,100),
                  ylim=c(0,100))
ggplotly(p)

Coordinated multiple view with plotly

Highlight_key() of plotly package is used as shared data. Two scatterplots will be created by using ggplot2 functions. Lastly, subplot() of plotly package is used to place them next to each other side-by-side.

d <- highlight_key(exam_data)
p1 <- ggplot(data=d, 
            aes(x = MATHS,
                y = ENGLISH)) +
  geom_point(size=1) +
  coord_cartesian(xlim=c(0,100),
                  ylim=c(0,100))

p2 <- ggplot(data=d, 
            aes(x = MATHS,
                y = SCIENCE)) +
  geom_point(size=1) +
  coord_cartesian(xlim=c(0,100),
                  ylim=c(0,100))
subplot(ggplotly(p1),
        ggplotly(p2))

crosstalk methods

Interactive data table: DT packages

DT::datatable(exam_data, class= "compact")

Linked brushing crosstalk method

d <- highlight_key(exam_data) 
p <- ggplot(d, 
            aes(ENGLISH, 
                MATHS)) + 
  geom_point(size=1) +
  coord_cartesian(xlim=c(0,100),
                  ylim=c(0,100))

gg <- highlight(ggplotly(p),        
                "plotly_selected")  

crosstalk::bscols(gg,               
                  DT::datatable(d), 
                  widths = 5)        
Setting the `off` event (i.e., 'plotly_deselect') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.

Animated statistical graphics

Getting Started

Install and load R packages

pacman::p_load(readxl, gifski, gapminder,
               plotly, gganimate, tidyverse)

Import data

col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
                      sheet="Data") %>%
  mutate_each_(funs(factor(.)), col) %>%
  mutate(Year = as.integer(Year))
Warning: `mutate_each_()` was deprecated in dplyr 0.7.0.
ℹ Please use `across()` instead.
Warning: `funs()` was deprecated in dplyr 0.8.0.
ℹ Please use a list of either functions or lambdas:

# Simple named list: list(mean = mean, median = median)

# Auto named with `tibble::lst()`: tibble::lst(mean, median)

# Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))

gganimate method

Build a static population bubble plot

ggplot(globalPop, aes(x = Old, y = Young, 
                      size = Population, 
                      colour = Country)) +
  geom_point(alpha = 0.7, 
             show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(title = 'Year: {frame_time}', 
       x = '% Aged', 
       y = '% Young') 

Build the animated bubble plot

transition_time() of gganimate is used to create transition through distinct states in time (i.e. Year). ease_aes() is used to control easing of aesthetics. The default is linear. Other methods are: quadratic, cubic, quartic, quintic, sine, circular, exponential, elastic, back, and bounce.

ggplot(globalPop, aes(x = Old, y = Young, 
                      size = Population, 
                      colour = Country)) +
  geom_point(alpha = 0.7, 
             show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(title = 'Year: {frame_time}', 
       x = '% Aged', 
       y = '% Young') +
  transition_time(Year) +       
  ease_aes('linear')          

plotly method

Build animated bubble plot with ggplotly()

gg <- ggplot(globalPop, 
       aes(x = Old, 
           y = Young, 
           size = Population, 
           colour = Country)) +
  geom_point(aes(size = Population,
                 frame = Year),
             alpha = 0.7, 
             show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(x = '% Aged', 
       y = '% Young')
Warning in geom_point(aes(size = Population, frame = Year), alpha = 0.7, :
Ignoring unknown aesthetics: frame
ggplotly(gg)
Warning in p$x$data[firstFrame] <- p$x$frames[[1]]$data: number of items to
replace is not a multiple of replacement length

Build animated buble plot with plot_ly()

bp <- globalPop %>%
  plot_ly(x = ~Old, 
          y = ~Young, 
          size = ~Population, 
          color = ~Continent, 
          frame = ~Year, 
          text = ~Country, 
          hoverinfo = "text",
          type = 'scatter',
          mode = 'markers'
          )
bp
Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.

Warning: `line.width` does not currently support multiple values.